#pragma once

#include <memory>
#include <functional>
#include <system_error>


class LoopService;
class TimerEventWatcher;
class DeadLineTimer;

typedef std::shared_ptr<DeadLineTimer> DeadLineTimerPtr;

class DeadLineTimer : public std::enable_shared_from_this<DeadLineTimer>
{
    DeadLineTimer(const DeadLineTimer&) = delete;
    void operator=(const DeadLineTimer&) = delete;
public:
	typedef std::function<void(const std::error_code&)> Functor;

	// @brief Create a timer. When the timer is timeout, the functor f will
	//  be invoked automatically.
	// @param evloop - The EventLoop runs this timer
	// @param timeout - The timeout when the timer is invoked
	// @param f -
	// @param periodic - To indicate this timer whether it is a periodic timer.
	//  If it is true this timer will be automatically invoked periodic.
	// @return evpp::InvokeTimerPtr - The user layer can hold this shared_ptr
	//  and can cancel this timer at any time.
	static DeadLineTimerPtr create(LoopService* evloop,int timeout,bool periodic);

	~DeadLineTimer(){}

	// It is thread safe.
	// Start this timer.
	void start(const Functor& f);

	// Cancel the timer and the cancel_callback_ will be invoked.
	void cancel();

private:
	DeadLineTimer(LoopService* evloop, int timeout, bool periodic);
	void _on_timer_triggered();
	void _on_canceled();

private:
	LoopService* loop_;
	int timeout_;
	Functor functor_;
	std::shared_ptr<TimerEventWatcher> timer_;
	bool periodic_;
	std::shared_ptr<DeadLineTimer> self_; // Hold myself
};

